import { NetEvent, NetManagerEvent, NetManagerState, NetState, SocketType } from "../../Enum/NetEnums";
import BaseSocket from "./BaseSocket";
import { EventTarget } from "cc";
import ConnectedData from "./ConnectedData";
/**
 * using createSocket and syncConnect
 */
export default class SocketManager extends EventTarget {// 管理单个sokcet，这样更好理解，编程更简洁，越复杂的东西越不好用
    socket: BaseSocket;
    /** 连接状态 */
    stateNet: NetManagerState = NetManagerState.disconnected;
    public createSocket(ip: string, port: number, socketType: SocketType): BaseSocket {
        let sk = new BaseSocket();
        sk.init(ip, port, socketType);
        this.socket = sk;
        this.bindSocketInitEvents(this.socket); // 绑定事件
        return sk;
    }

    public connect() {
        this.changeSocketManagerState(NetManagerState.connecting);
        this.socket.connect();
    }
    public connectSync() {// 等待关闭
        return new Promise<ConnectedData>((resolve) => {
            this.once(NetManagerEvent.connectServer, (connectedData: ConnectedData) => { resolve(connectedData); });
            this.changeSocketManagerState(NetManagerState.connecting);
            this.socket.connect();
        });
    }
    private changeSocketManagerState(connecting: NetManagerState) {
        console.log(NetManagerState[this.stateNet]
            , " change State ", NetManagerState[connecting]);
        this.stateNet = connecting;
    }
    // socket网络连接状态事件绑定
    private bindSocketInitEvents(socket: BaseSocket) {
        socket.on(NetEvent.onNetOpen, () => { this.socketOnOpen(); });
        socket.on(NetEvent.onNetClose, () => { if (this.stateNet != NetManagerState.disconnected) this.socketOnAutoClose(); });
        socket.on(NetEvent.onNetTimeOut, () => { if (this.stateNet != NetManagerState.disconnected) this.closeSocket(); });
        socket.on(NetEvent.onNetError, () => { this.socketOnError(); });
    }
    /**
     * 连接已断开 return
     * 连接中 分发连接失败事件 关闭连接
     * 已连接 关闭连接
     */
    private socketOnError() {
        console.log("socketOnError");
        if (this.stateNet == NetManagerState.disconnected) {// 不在连接状态
            console.log("NetManager socketOnError socket error");
            return;
        }
        else if (this.stateNet == NetManagerState.connected) {
            this.closeSocket();
        } else if (this.stateNet == NetManagerState.connecting) {
            this.changeSocketManagerState(NetManagerState.disconnected);
            this.dispatchConnectEvent(false);// 连接失败
        }
    }
    /**客户端主动关闭连接*/
    public closeSocket(isForce?: boolean) {//NetEvent.onNetTimeOut
        console.log("客户端主动关闭连接");
        if (this.stateNet == NetManagerState.disconnected) {
            console.log("连接已关闭");
        } else if (this.stateNet == NetManagerState.connecting) {
            this.changeSocketManagerState(NetManagerState.disconnected);
            this.socket.close();
            this.dispatchConnectEvent(false);
        } else if (this.stateNet == NetManagerState.connected) {
            this.changeSocketManagerState(NetManagerState.disconnected);
            this.socket.close();
            this.dispatchCloseEvent();
        }
    }
    /**
     * 未在连接状态则打印 客户端主动关闭连接会出现这种状态
     * 连接中则分发连接失败 客户端正在连接而服务器断开会出现这种情况
     * 已连接则关闭连接 服务器断开会出现这种情况
     */
    private socketOnAutoClose() {//NetManagerEvent.onDisconnected
        console.log("socketOnAutoClose");
        if (this.stateNet == NetManagerState.disconnected) {
            console.log("连接已经关闭");
        } else if (this.stateNet == NetManagerState.connecting) {
            this.changeSocketManagerState(NetManagerState.disconnected);
            this.dispatchConnectEvent(false);// 连接失败
        } else if (this.stateNet == NetManagerState.connected) {
            this.closeSocket();
        }
    }
    private dispatchCloseEvent() {
        this.emit(NetManagerEvent.onClose);
    }
    /** 客户端正在连接服务器事件分发，等待连接成功与否 */
    private dispatchConnectEvent(isSuccess: boolean) {
        this.emit(NetManagerEvent.connectServer, new ConnectedData(isSuccess));
    }

    private socketOnOpen() {
        if (this.stateNet == NetManagerState.connecting) {
            this.changeSocketManagerState(NetManagerState.connected);
            this.dispatchConnectEvent(true);
        } else {
            console.log(this.stateNet, "#SocketManager socketOnOpen SocketManagerState is not connecting");
        }
    }

    isConnected(): boolean {
        return this.stateNet == NetManagerState.connected;
    }

}